//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package ch.qos.logback.core;

import ch.qos.logback.core.joran.spi.ConsoleTarget;
import ch.qos.logback.core.status.Status;
import ch.qos.logback.core.status.WarnStatus;
import ch.qos.logback.core.util.Loader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 适用于场景：
 * 如果说外部引用的jar包，sdk之类的东西出现了bug。需要自己去修复bug，那么就需要这个样子将对应的代码复制出来。
 * 命名成相同的包名。放在自己的java目录下。然后根据JVM的类加载机制。会优先加载自己的java路径下的类，而且哪怕后期
 * 有相同名称的类（完整限定名）。也不会再次加载，只会是旧的加载类继续运行。利用这个机制，我们便可以直接在不提交issue，
 * 等待官方回复的情况下来手动的修复bug。
 *
 * ok那么下面这里就是被改过的ConsoleAppender
 * @param <E>
 */
public class ConsoleAppender<E> extends OutputStreamAppender<E> {
    public static final String testNiubi = "JIE bro niubility";
    protected ConsoleTarget target;
    protected boolean withJansi;
    private static final String AnsiConsole_CLASS_NAME = "org.fusesource.jansi.AnsiConsole";
    private static final String wrapSystemOut_METHOD_NAME = "wrapSystemOut";
    private static final String wrapSystemErr_METHOD_NAME = "wrapSystemErr";
    private static final Class<?>[] ARGUMENT_TYPES = new Class[]{PrintStream.class};

    public ConsoleAppender() {
        this.target = ConsoleTarget.SystemOut;
        this.withJansi = false;
    }

    public void setTarget(String value) {
        ConsoleTarget t = ConsoleTarget.findByName(value.trim());
        if (t == null) {
            this.targetWarn(value);
        } else {
            this.target = t;
        }

    }

    public String getTarget() {
        return this.target.getName();
    }

    private void targetWarn(String val) {
        Status status = new WarnStatus("[" + val + "] should be one of " + Arrays.toString(ConsoleTarget.values()), this);
        status.add(new WarnStatus("Using previously set target, System.out by default.", this));
        this.addStatus(status);
    }

    public void start() {
        OutputStream targetStream = this.target.getStream();
        if (this.withJansi) {
            targetStream = this.wrapWithJansi(targetStream);
        }

        this.setOutputStream(targetStream);
        super.start();
    }

    private OutputStream wrapWithJansi(OutputStream targetStream) {
        try {
            this.addInfo("Enabling JANSI AnsiPrintStream for the console.");
            ClassLoader classLoader = Loader.getClassLoaderOfObject(this.context);
            Class<?> classObj = classLoader.loadClass("org.fusesource.jansi.AnsiConsole");
            String methodName = this.target == ConsoleTarget.SystemOut ? "wrapSystemOut" : "wrapSystemErr";
            Method method = classObj.getMethod(methodName, ARGUMENT_TYPES);
            return (OutputStream)method.invoke((Object)null, new PrintStream(targetStream));
        } catch (Exception var6) {
            this.addWarn("Failed to create AnsiPrintStream. Falling back on the default stream.", var6);
            return targetStream;
        }
    }

    public boolean isWithJansi() {
        return this.withJansi;
    }

    public void setWithJansi(boolean withJansi) {
        this.withJansi = withJansi;
    }
}
